package com.guochu.org.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.guochu.common.AuthService;
import com.guochu.common.ResultMap;
import com.guochu.common.annotation.CloseAuth;
import com.guochu.common.infrastructure.Identity;
import com.guochu.org.entity.User;
import com.guochu.org.service.UserService;
import com.guochu.org.entity.Login;
import com.guochu.org.service.LoginService;
import com.guochu.utils.MapUtils;
import com.guochu.utils.redis.RedisUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 登录账号表 (Login)表控制层
 *
 * @author bunting.wei
 * @since 2020-12-11 13:06:14
 */
@RestController
@RequestMapping("sys/login")
public class LoginController {
    /**
     * 服务对象(service层)
     */
    @Resource
    private LoginService loginService;
    @Resource
    private UserService userService;
    @Autowired
    private AuthService authService;
    @Resource
    RedisUtil redis;

    /**
     * 登录时加密常量
     */
    private final String prefix = "$#1a&c";

    /**
     * 账号密码登录，pc管理后台
     * 入参为 account（账号）、password（密码）
     *
     * @param limit
     * @return
     */
    @CloseAuth(value = true)
    @RequestMapping(value = "/loginOn", method = RequestMethod.POST)
    public ResultMap loginOn(@RequestBody Map<String, Object> limit) {
        String account = MapUtils.getString(limit, "account");
        String password = MapUtils.getString(limit, "password");
        // 登录名是否存在
        Map<String, Object> param = new HashMap<>();
        param.put("account", account);
        List<Login> whetherUser = this.loginService.queryAllByLimit(param);
        if (whetherUser.size() > 1) {
            return ResultMap.error("A0200", "用户登陆异常");
        } else if (whetherUser.size() == 0) {
            return ResultMap.error("A0201", "用户账户不存在");
        } else {
            Login login = whetherUser.get(0);
            if (login.getEnabledMark().equals(0)) {
                //Enabledmark==0时，属于用户账号已被禁用
                return ResultMap.error("A0202", "用户账户被冻结");
            }
            // 密码是否正确
            // md5加密获取加密的密码
            String dbPassword = DigestUtils.md5Hex(prefix + password);

            if (!dbPassword.equals(login.getPassword())) {
                //用户密码错误
                return ResultMap.error("A0210", "用户密码错误");
            }
            // 获取登录人信息
            User user = userService.queryById(login.getUserId());
            // 获取token
            String token = tokenHandler(login, user);
            // 返回token
            return ResultMap.success().put("token", token).put("user", user).put("login", login);
        }
    }

    /**
     * 登录之后的token设置
     *
     * @param login
     * @return
     */
    private String tokenHandler(Login login, User user) {
        // 添加缓存
        Identity identity = new Identity();
        identity.setLogin(login);
        identity.setUser(user);
        // Token工具类
        return authService.getToken(identity);
    }

    /**
     * 获取当前登录用户信息
     *
     * @return
     */
    @RequestMapping(value = "/getLoginUser", method = RequestMethod.POST)
    public ResultMap getLoginUser() {
        Identity identity = authService.getIdentity();
        if (null != identity) {
            User user = this.userService.queryById(identity.getUser().getId());
            identity.setUser(user);
            Login login = this.loginService.queryById(identity.getLogin().getId());
            identity.setLogin(login);
            authService.refreshToken(identity);
            if (null == user) {
                return ResultMap.error("已过期");
            }
        }
        return ResultMap.success().put("item", identity);
    }

    /**
     * 小程序获取用户的session_key和openid
     *
     * @param limit
     * @return
     */
    @CloseAuth(value = true)
    @RequestMapping(value = "/getSessionKey", method = RequestMethod.POST)
    public ResultMap getSessionKey(@RequestBody Map<String, Object> limit) {
        String appid = "wx38316ee4df1944cd";
        String secret = "23054fece75bce7dbc5026124d769e6b";
        String urlName = "https://api.weixin.qq.com/sns/jscode2session?appid=" + appid + "&secret=" + secret + "&js_code=" + MapUtils.getString(limit, "code") + "&grant_type=authorization_code";
        Map<String, Object> first = first(urlName);
        String session_key = MapUtils.getString(first, "session_key");
        String openid1 = MapUtils.getString(first, "openid");
        return ResultMap.success().put("session_key", session_key).put("open_id", openid1);
    }

    /**
     * 本机号码一键登录
     */
    @CloseAuth(value = true)
    @RequestMapping(value = "/phoneOneClickLogin", method = RequestMethod.POST)
    public ResultMap phoneOneClickLogin(@RequestBody Map<String, Object> limit) {
        Map<String, Object> loginMap = new HashMap<>();
        loginMap.put("account", MapUtils.getString(limit, "phoneNumber"));
        List<Login> logins = this.loginService.queryAllByLimit(loginMap);
        User user = new User();
        String token = "";
        if (logins.size() < 1) {
            // 注册
            user.setUserName("微信用户");// 用户名称
            user.setGender(1);// 性别 1男 2女
            this.userService.insert(user);
            Login login = new Login();
            login.setWeChatKey(MapUtils.getString(limit, "openId"));
            login.setUserId(user.getId());
            login.setAccount(MapUtils.getString(limit, "phoneNumber"));
            this.loginService.insert(login);
            logins.add(login);
            // 获取token
            token = tokenHandler(login, user);
        } else {
            user = this.userService.queryById(logins.get(0).getUserId());
            token = tokenHandler(logins.get(0), user);
        }
        // 返回token
        return ResultMap.success().put("token", token).put("user", user).put("login", logins.get(0));
    }


    /**
     * 根据微信code自动登录
     *
     * @param limit
     * @return
     */
    @CloseAuth(value = true)
    @RequestMapping(value = "/loginByWxCode", method = RequestMethod.POST)
    public ResultMap loginByWxCode(@RequestBody Map<String, Object> limit) {
        String urlName = "https://api.weixin.qq.com/sns/jscode2session?appid=wx38316ee4df1944cd&secret=23054fece75bce7dbc5026124d769e6b&js_code=" + MapUtils.getString(limit, "code") + "&grant_type=authorization_code";
        Map<String, Object> first = first(urlName);
        String openid = MapUtils.getString(first, "openid");
        Map<String, Object> loginMap = new HashMap<>();
        loginMap.put("weChatKey", openid);
        List<Login> logins = this.loginService.queryAllByLimit(loginMap);
        if (logins.size() > 0) {
            User user = this.userService.queryById(logins.get(0).getUserId());
            String token = tokenHandler(logins.get(0), user);
            // 返回token
            return ResultMap.success().put("token", token).put("user", user).put("login", logins.get(0));
        } else {
            return ResultMap.error("A0201", "用户账户不存在");
        }
    }

    /**
     * 根据userId自动登录，小程序不可用存在bug
     *
     * @param limit
     * @return
     */
    @CloseAuth(value = true)
    @RequestMapping(value = "/loginSimulation", method = RequestMethod.POST)
    public ResultMap loginSimulation(@RequestBody Map<String, Object> limit) {
        String userId = MapUtils.getString(limit, "userId");
        Map<String, Object> loginMap = new HashMap<>();
        loginMap.put("userId", userId);
        List<Login> logins = this.loginService.queryAllByLimit(loginMap);
        if (logins.size() > 0) {
            User user = this.userService.queryById(userId);
            String token = tokenHandler(logins.get(0), user);
            // 返回token
            return ResultMap.success().put("token", token).put("user", user).put("login", logins.get(0));
        } else {
            return ResultMap.error("A0201", "用户账户不存在");
        }
    }

    /**
     * 验证码登录
     *
     * @param limit
     * @return
     */
    @CloseAuth(true)
    @RequestMapping(value = "/verification", method = RequestMethod.POST)
    public ResultMap verification(@RequestBody Map<String, Object> limit) {
        String smsCode = MapUtils.getString(limit, "smsCode");
        String account = MapUtils.getString(limit, "account");
        //验证验证码是否一致
        Object o = redis.get("smsVer_" + account);

        if (null == o) {
            return ResultMap.error("验证码已失效");
        }
        if (smsCode.equals(o.toString())) {
            Map<String, Object> loginMap = new HashMap<>();
            loginMap.put("account", account);
            List<Login> logins = this.loginService.queryAllByLimit(loginMap);
            User user = new User();
            String token = "";
            if (logins.size() < 1) {
                // 注册
                user.setUserName("新用户");// 用户名称
                user.setGender(1);// 性别
                user.setHeadIcon("https://gjwy.nephil.cn:45/group1/M00/00/05/rBII42KNyXSAZ_neAADNUesqoAs064.png");// 头像
                this.userService.insert(user);
                Login login = new Login();
                login.setAccount(account);
                login.setUserId(user.getId());
                this.loginService.insert(login);
                logins.add(login);
                // 获取token
                token = tokenHandler(login, user);
            } else {
                user = this.userService.queryById(logins.get(0).getUserId());
                token = tokenHandler(logins.get(0), user);
            }
            redis.remove("smsVer_" + account);
            return ResultMap.success().put("token", token).put("user", user).put("login", logins.get(0));
        } else {
            return ResultMap.error("验证码错误");
        }
    }

    public Map<String, Object> first(String url) {
        String s = applyUrl(url);
        JSONObject object = JSON.parseObject(s);
        Map<String, Object> jsonToMap = JSONObject.parseObject(object.toJSONString());
        return jsonToMap;
    }

    public String applyUrl(String url) {
        String result = "";
        BufferedReader in = null;
        try {
            URL realUrl = new URL(url);
            //打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            //建立实际的连接
            conn.connect();
            //获取所有响应头字段
            Map<String, List<String>> map = conn.getHeaderFields();
            //遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            //定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += "\n" + line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常！" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 系统登出
     *
     * @return
     */
    @RequestMapping(value = "/logOut", method = RequestMethod.POST)
    public ResultMap logOut() {

        authService.loginOut(authService.getTokenString());
        return ResultMap.success();
    }
}
